#include "LampManager.h"
#include "F3LampInterfaces.h"
#include "TurnLampStateMachine.h"
#include "FrontLampStateMachine.h"
#include "Animations.h"
#include "LowPwr.h"
#include <string.h>

LampModel                g_LampModel;
DayTimeAndPosLampView    g_DayTimeAndPosLampView;
DlpModelView             g_DlpModelView;
HiBeamView               g_HiBeamView;
LeFrntTrunLampView       g_LeFrntTrunLampView;
LoBeamView               g_LoBeamView;
Po2LedView               g_Po2LedView;
StarrySkyView            g_StarrySkyView;
CornerLampView           g_CornerLampView;
RibbonAnimationModel     g_RibbonAnimationModel;
SystemSleepWeakupModel   g_SystemSleepWeakupModel;
RibbonView               g_RibbonView;

static void initViews(void)
{
    memset(&g_LampModel, 0, sizeof(LampModel));
    memset(&g_DayTimeAndPosLampView, 0, sizeof(DayTimeAndPosLampView));
    memset(&g_DlpModelView, 0, sizeof(DlpModelView));
    memset(&g_HiBeamView, 0, sizeof(HiBeamView));
    memset(&g_LeFrntTrunLampView, 0, sizeof(LeFrntTrunLampView));
    memset(&g_LoBeamView, 0, sizeof(LoBeamView));
    memset(&g_Po2LedView, 0, sizeof(Po2LedView));
    memset(&g_StarrySkyView, 0, sizeof(StarrySkyView));
    memset(&g_CornerLampView, 0, sizeof(CornerLampView));
    memset(&g_RibbonView, 0, sizeof(RibbonView));
    memset(&g_RibbonAnimationModel, 0, sizeof(RibbonAnimationModel));
    memset(&g_SystemSleepWeakupModel, 0, sizeof(SystemSleepWeakupModel));

    g_DayTimeAndPosLampView.this_ = &g_DayTimeAndPosLampView;
    g_DayTimeAndPosLampView.model_ = &g_LampModel.dayTimeAndPosnLampModel_;
    g_DayTimeAndPosLampView.view = execute_TimeLampView;

    g_DlpModelView.this_ = &g_DlpModelView;
    g_DlpModelView.model_ = &g_LampModel.dlpModel_;
    g_DlpModelView.view = execute_dlpView;

    g_HiBeamView.this_ = &g_HiBeamView;
    g_HiBeamView.model_ = &g_LampModel.hiBeamModel_;
    g_HiBeamView.view = execute_HiBeamView;

    g_LeFrntTrunLampView.this_ = &g_LeFrntTrunLampView;
    g_LeFrntTrunLampView.model_ = &g_LampModel.leftFrontTurnLampModel_;
    g_LeFrntTrunLampView.view =execute_LeFrntTrunLampView;

    g_LoBeamView.this_ = &g_LoBeamView;
    g_LoBeamView.model_ = &g_LampModel.loBeamModel_;
    g_LoBeamView.view = execute_LoBeamView;

    g_Po2LedView.this_ = &g_Po2LedView;
    g_Po2LedView.model_ = &g_LampModel.po2LedModel_;
    g_Po2LedView.view = execute_po2LedView;

    g_StarrySkyView.this_ = &g_StarrySkyView;
    g_StarrySkyView.model_ = &g_LampModel.StarrySkyModel_;
    g_StarrySkyView.view = execute_StarrySkyView;

    g_CornerLampView.this_ = &g_CornerLampView;
    g_CornerLampView.model_ = &g_LampModel.CornerLampModel_;
    g_CornerLampView.view = execute_CornerView;

    g_RibbonView.this_ = &g_RibbonView;
    g_RibbonView.model_ = &g_LampModel.ribbonModel_;
    g_RibbonView.view = execute_RibbonView;

    g_SystemSleepWeakupModel.lampsOnOffMask_ = 0x00;
    g_SystemSleepWeakupModel.systemState_ = System_Init;

}

static void rememberTurnLastState(void)
{
    memcpy(&g_DayTimeAndPosLampView.lastModel_, g_DayTimeAndPosLampView.model_, sizeof(DayTimeAndPosnLampModel));
    memcpy(&g_LeFrntTrunLampView.lastModel_, g_LeFrntTrunLampView.model_, sizeof(LeftFrontTurnLampModel));
    memcpy(&g_StarrySkyView.lastModel_, g_StarrySkyView.model_, sizeof(StarrySkyModel));
    memcpy(&g_RibbonAnimationModel.lastPosnMode_, &g_RibbonAnimationModel.posnMode_, sizeof(RibbonAnimationModelType));
}

static void rememberFrontLastState(void)
{
    memcpy(&g_DlpModelView.lastModel_, g_DlpModelView.model_, sizeof(DlpModel));
    memcpy(&g_HiBeamView.lastModel_, g_HiBeamView.model_, sizeof(HiBeamModel));
    memcpy(&g_LoBeamView.lastModel_, g_LoBeamView.model_, sizeof(LoBeamModel));
    memcpy(&g_Po2LedView.lastModel_, g_Po2LedView.model_, sizeof(PO2_LEDModel));
    memcpy(&g_CornerLampView.lastModel_, g_CornerLampView.model_, sizeof(CornerLampModel));
    memcpy(&g_RibbonView.lastModel_, g_RibbonView.model_, sizeof(RibbonModel));
    memcpy(&g_RibbonAnimationModel.lastLobeamMode_, &g_RibbonAnimationModel.lobeamMode_, sizeof(RibbonAnimationModelType));
}

static void viewTurnLamp(void)
{
    g_DayTimeAndPosLampView.view(g_DayTimeAndPosLampView.this_);
    g_LeFrntTrunLampView.view(g_LeFrntTrunLampView.this_);
    g_StarrySkyView.view(g_StarrySkyView.this_);
}

static void viewFrontLamp(void)
{
    g_DlpModelView.view(g_DlpModelView.this_);
    g_HiBeamView.view(g_HiBeamView.this_);
    g_LoBeamView.view(g_LoBeamView.this_);
    g_CornerLampView.view(g_CornerLampView.this_);
    g_Po2LedView.view(&g_Po2LedView);
    g_RibbonView.view(&g_RibbonView);
}

void InitApplication(void)
{
    Set_LampCtrl_StarrySkyAndPo2Lamp_Enable(true);
    Set_HiBeam_OnOffState(false);
    Set_LoBeam_OnOffState(false);
    initViews();
    InitTurnStateMachine();
    InitFrontStateMachine();
    initLeFrntTurnLampRibbonUnlockAnimationManager();
    initLobeamLampRibbonUnlockAnimationManager();
    initLeFrntTurnLampRibbonLockAnimationManager();
    initLobeamLampRibbonLockAnimationManager();
}

static void updateFrontLampUsageMode(UsageModeFlag usageMode)
{
    if(IsSystemGoingToSleep())
    {
        g_FrontNewState.usageModeState_ = UsageModeState_Sleep;
    }
    else
    {
        if(usageMode == UsageMode_Inactive || usageMode == UsageMode_Convenience || usageMode == UsageMode_OTA_Updating || usageMode == UsageMode_Remote)
        {
            RibbonCtrlCmd cmd = Get_CANSIG_LoBeamEffectCtrlCmd();
            if(cmd == RibbonCtrl_Initial || cmd == RibbonCtrl_Off || cmd == RibbonCtrl_NoRequest || cmd == RibbonCtrl_Invalid)
            {
                g_FrontNewState.usageModeState_ = UsageModeState_Normal;
            }
            else
            {
                g_FrontNewState.usageModeState_ = UsageModeState_Ribbon;
            }
        }
        else
        {
            g_FrontNewState.usageModeState_ = UsageModeState_Normal;
        }
    }
}

static void transitionAndExecuteFrontLampModel()
{
    switch (g_FrontNewState.usageModeState_)
    {
        case UsageModeState_Normal:
            FrontNormalStateTransition();
            break;

        case UsageModeState_Ribbon:
            FrontRibbonStateTransition();
            break;

        case UsageModeState_Sleep:
            FrontSleepStateTransition();
            break;
        
        default:
            break;
    }

    FrontStateMachineExecute();
    
    UpdateUsageModeState(g_FrontNewState.usageModeState_, &g_FrontLastState.usageModeState_);
}

static void updateTurnLampUsageMode(UsageModeFlag usageMode)
{
    //sleep mode have higher priority
    if(IsSystemGoingToSleep())
    {
        g_TurnNewState.usageModeState_ = UsageModeState_Sleep;
    }
    else
    {
        if(usageMode == UsageMode_Inactive || usageMode == UsageMode_Convenience || usageMode == UsageMode_OTA_Updating || usageMode == UsageMode_Remote)
        {
            RibbonCtrlCmd cmd = Get_CANSIG_FrntRibbonLampEffectCtrlCmd();
            if(cmd == RibbonCtrl_Initial || cmd == RibbonCtrl_Off || cmd == RibbonCtrl_NoRequest || cmd == RibbonCtrl_Invalid)
            {
                g_TurnNewState.usageModeState_ = UsageModeState_Normal;
            }
            else
            {
                g_TurnNewState.usageModeState_ = UsageModeState_Ribbon;
            }
        }
        else
        {
            g_TurnNewState.usageModeState_ = UsageModeState_Normal;
        }
    }
}

static void transitionAndExecuteTurnLampModel()
{
    switch(g_TurnNewState.usageModeState_)
    {
        case UsageModeState_Ribbon:
        {
            TurnRibbonStateTransition();
            break;
        }

        case UsageModeState_Normal:
        {
            TurnNormalStateTransition();
            break;
        }

        case UsageModeState_Sleep:
        {
            TurnSleepStateTransition();
            break;
        }

        default:
        {
            // todo
            // TurnNormalStateTransition(); 
            break;
        }
    }

    TurnStateMachineExecute();

    UpdateUsageModeState(g_TurnNewState.usageModeState_, &g_TurnLastState.usageModeState_);
}


void OnAppTask_5ms(void)
{
    UsageModeFlag usageMode = Get_CANSIG_UsageMode();
    updateFrontLampUsageMode(usageMode);
    updateTurnLampUsageMode(usageMode);
    if(g_TurnNewState.usageModeState_ == UsageModeState_Ribbon)
    {
        transitionAndExecuteTurnLampModel();
        viewTurnLamp();
        rememberTurnLastState();
    }

    if(g_FrontNewState.usageModeState_ == UsageModeState_Ribbon)
    {
        transitionAndExecuteFrontLampModel();
        viewFrontLamp();
        rememberFrontLastState();
    }
}

void OnAppTask_10ms(void)
{
    if(g_TurnNewState.usageModeState_ != UsageModeState_Ribbon)
    {
        transitionAndExecuteTurnLampModel();
        viewTurnLamp();
        rememberTurnLastState();
    }

    if(g_FrontNewState.usageModeState_ != UsageModeState_Ribbon)
    {
        transitionAndExecuteFrontLampModel();
        viewFrontLamp();
        rememberFrontLastState();
    }
}

void OnAppTask_100ms(void)
{
    if(IsSystemRequestSleep())
    {
        g_SystemSleepWeakupModel.systemState_ = System_Sleep;
    }
    else
    {
        if(g_SystemSleepWeakupModel.systemState_ == System_Init)
        {
            SystemCtrl_StartWeakup();
        }
        g_SystemSleepWeakupModel.systemState_ = System_Weakup;
    }
}
